package cn.wolfocde.wolf2w.interceptor;

import cn.wolfocde.wolf2w.annotation.RequireLoginAnnotation;
import cn.wolfocde.wolf2w.domain.UserInfo;
import cn.wolfocde.wolf2w.redis.service.IUserInfoRedisService;
import cn.wolfocde.wolf2w.util.JsonResult;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 登录拦截器
 * 目的是让所有的请求先经过拦截器判断是否登录过了才能访问资源
 * 或者做区分拦截控制(比如:有登录才能评论游记)
 */
public class CheckLoginInterceptor implements HandlerInterceptor {
    @Autowired
    private IUserInfoRedisService userInfoRedisService;
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//    (每个动态请求的路径都有对应的映射方法的所有的信息
//   比如:映射方法的注解和方法名,参数,返回值等数据)封装成的handlerMethod对象,
// 这个对象通过请求路径获取到后,封装到拦截器的方法的参数上
//    静态请求和跨域请求是没有对应的映射方法的,所有没有对应的handlerMethod对象,
// 所有拦截器的方法的参数handler不是handlerMethod对象,
//   如果是静态请求和跨域请求是不必要拦截的,可以通过判断handler是不是handlerMethod对象,控制:
//    比如,不是,就放行,不拦截它们(因为在拦截器拦截跨域请求,就会报错,不要拦截他))

        //1.静态请求放它走(请求是访问静态页面的就放行,让它访问);
        //2.请求是跨域请求的,拦截器也放行,让它访问控制器和启动类.启动类配置了,解决跨域问题的配置,跨域请求就可以访问我们的项目
        if (! (handler instanceof HandlerMethod)) {//如果handler是不是handlerMethod类的实例对象,就放行
            return true ;
        }

        /**
         * 只要你是请求就给你加30分钟;
         如果这个不在中间的if外面就会每次请求不加
         30分钟了:(造成用户每30分钟后,要不断登录)
         */
        String token = request.getHeader("token");
        UserInfo user = userInfoRedisService.getCurrentUserByToken(token);
        HandlerMethod handlerMethod = (HandlerMethod) handler;

//        只要你是动态请求访问映射方法,都把映射方法的参数,注解等信息封装在handlerMethod对象里面了,

        //每个请求过来先判断它对应访问的映射方法有没有RequireLoginAnnotation这个注解,没有直接放行;有就进行登录控制

//        判断用户对象为空,这样抽到if里面后,如果没有贴这个注解,是不是可以不登录就访问接口了?
//        是的,那些映射方法没有贴注解,意思本来就是预留给别人不用登录就访问的(先吸引人来浏览平台).
        if (handlerMethod.hasMethodAnnotation(RequireLoginAnnotation.class)) {
            //有注解,但是查询redis的当前用户是空值,就拦截,并且让它回去登录
            //redis的用户对象为空,说明还没有登录,不给登录
            if (user==null) {
                //提示用户的信息是中文可能乱码
                response.setContentType("application/json;charset=utf-8");
                //提示用户先登录
                String jsonResult = JSON.toJSONString(JsonResult.noLogin());
                response.getWriter().write(jsonResult);
                return false;
            }
        //  有注解,查询到redis的当前用户有值(表示已经登录了),就继续执行下面代码放行
        }



        //如果登录了,就继续执行到这里登录
        return true;
    }
}
